package com.hmy.contract.service.contract.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hmy.ccp.common.dto.BaseDto;
import com.hmy.ccp.common.dto.ContextUserInfo;
import com.hmy.ccp.error.exception.HMYRuntimeException;
import com.hmy.ccp.starter.web.utils.UserContextUtil;
import com.hmy.contract.bo.request.contract.AreaManagerApprovalContractRequest;
import com.hmy.contract.bo.request.contract.ContractApprovalHistoryRequest;
import com.hmy.contract.bo.request.contract.RiskMinisterApprovalContractRequest;
import com.hmy.contract.bo.response.contract.AreaManagerApprovalContractResponse;
import com.hmy.contract.bo.response.contract.ContractApprovalHistoryResponse;
import com.hmy.contract.bo.response.contract.RiskMinisterApprovalContractResponse;
import com.hmy.contract.commons.enums.ContractStatusEnum;
import com.hmy.contract.dal.mapper.ContractMapper;
import com.hmy.contract.dal.po.ContractPo;
import com.hmy.contract.manager.order.OrderFeignClientManager;
import com.hmy.contract.manager.uaa.UaaFeignClientManager;
import com.hmy.contract.manager.worklfow.FlowTaskClientManager;
import com.hmy.contract.service.contract.IContractApprovalService;
import com.hmy.contract.service.dto.contract.ApprovalCommentDto;
import com.hmy.contract.service.dto.contract.AreaManagerApprovalContractDto;
import com.hmy.contract.service.dto.contract.ContractExtensionFieldDto;
import com.hmy.contract.service.dto.contract.RiskMinisterApprovalContractDto;
import com.hmy.order.api.bo.request.ContractOrderStatusUpdateApiRequest;
import com.hmy.order.api.common.enums.OrderStatusEnum;
import com.hmy.order.api.common.enums.RoleEnum;
import com.hmy.workflow.api.bo.request.task.ApprovalTaskRequest;
import com.hmy.workflow.api.bo.response.task.ApprovalTaskResponse;
import com.hmy.workflow.api.enums.ApprovalStatusEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author seven.qi 齐胜南
 * @version 1.0
 * @description
 * @date 2024/3/13 15:06
 */
@Service
@Slf4j
public class ContractApprovalServiceImpl implements IContractApprovalService {

    @Resource
    private ContractMapper contractMapper;

    @Resource
    private UaaFeignClientManager uaaFeignClientManager;

    @Resource
    private FlowTaskClientManager flowTaskClientRpc;

    @Resource
    private OrderFeignClientManager orderFeignClientManager;

    @Override
    public ContractApprovalHistoryResponse getContractApprovalHistory(ContractApprovalHistoryRequest contractApprovalHistoryRequest) {
        return null;
    }

    @Override
    public RiskMinisterApprovalContractResponse riskMinisterApprovalContract(RiskMinisterApprovalContractRequest riskMinisterApprovalContractRequest) {
        log.info("riskMinisterApprovalContract request:{}", JSONUtil.toJsonStr(riskMinisterApprovalContractRequest));
        RiskMinisterApprovalContractDto dto = BeanUtil.copyProperties(riskMinisterApprovalContractRequest, RiskMinisterApprovalContractDto.class);
        setUserContextInfo(dto);
        // 1. 根据合同id查询合同信息
        ContractPo contractRo = selectContractPoByContractId(dto.getContractId());
        if (Objects.isNull(contractRo) || StrUtil.isEmpty(dto.getTaskId())) {
            throw new HMYRuntimeException(5010003);
        }
        dto.setProcessId(contractRo.getProcessId());
        // 2. 风控部长不判断用户部门权限
//        List<Long> deptIds = uaaFeignClientManager.getDeptIds(dto.getUpdaterId());
//        if (!deptIds.contains(contractRo.getDeptId())) {
//            throw new HMYRuntimeException(5010016);
//        }

        // 3. 判断用户角色权限
        if (!UserContextUtil.getCurrentUser().getRoles().contains(RoleEnum.RISK_MINISTER.getRoleType())) {
            throw new HMYRuntimeException(5010016);
        }

        // 4. 判断合同是否可以审核
//        if (!ContractStatusEnum.ORDER_STATUS_CAN_AUDIT.contains(contractRo.getStatus())) {
//            throw new HMYRuntimeException(5010015);
//        }
        Boolean auditResult = Boolean.FALSE;
        ApprovalTaskRequest approvalTaskRequest = new ApprovalTaskRequest();
        Map<String, Object> variables = new HashMap<>();
        if (dto.getPass()) {
            // 通过则设置对应的流程变量
            variables.put("riskManagerApproveResult", "agree");
            variables.put("businessStatus", ContractStatusEnum.APPROVED.getStatus());
            variables.put("businessStatusAlias", ContractStatusEnum.APPROVED.getStatusDesc());
            approvalTaskRequest.setComment(StringUtils.isEmpty(dto.getComment()) ? "通过" : dto.getComment());
        } else {
            // 不通过则驳回到销售经理
            variables.put("riskManagerApproveResult", "reject");
            variables.put("rejectCount", 1);
            variables.put("businessStatus", ContractStatusEnum.REJECT.getStatus());
            variables.put("businessStatusAlias", ContractStatusEnum.REJECT.getStatusDesc());
            approvalTaskRequest.setComment(StringUtils.isEmpty(dto.getComment()) ? "驳回" : dto.getComment());
        }
        approvalTaskRequest.setVariables(variables);
        approvalTaskRequest.setProcessInstanceId(dto.getProcessId());
        approvalTaskRequest.setTaskId(dto.getTaskId());
        approvalTaskRequest.setApprovalStatus(dto.getPass() ? ApprovalStatusEnum.PASS.getCode() : ApprovalStatusEnum.REJECT.getCode());
        ApprovalTaskResponse approvalTaskResponse = flowTaskClientRpc.complete(approvalTaskRequest);
        if (Objects.nonNull(approvalTaskResponse) && Objects.nonNull(approvalTaskResponse.getSuccess())) {
            auditResult = approvalTaskResponse.getSuccess();
        }

        // 6. 更新合同表
        if (auditResult) {
            ContractPo contractPo = new ContractPo();
            ContractExtensionFieldDto contractExtensionFieldDto = new ContractExtensionFieldDto();
            if (Objects.nonNull(JSONUtil.toBean(contractPo.getExtendedFields(), ContractExtensionFieldDto.class))) {
                contractExtensionFieldDto = JSONUtil.toBean(contractPo.getExtendedFields(), ContractExtensionFieldDto.class);
            }
            contractExtensionFieldDto.setApprovalComments(dto.getComment());
            contractPo.setExtendedFields(JSONUtil.toJsonStr(contractExtensionFieldDto));

            // 流程审批后更新状态
            if (Objects.nonNull(dto.getPass()) && Boolean.TRUE.equals(dto.getPass())) {
                contractPo.setStatus(ContractStatusEnum.APPROVED.getStatus());
                // 更新订单状态为合同已签署
                try {
                    orderFeignClientManager.updateContractOrderStatus(new ContractOrderStatusUpdateApiRequest(contractRo.getOrderId(), OrderStatusEnum.SIGNED_EXAMINE.getOrderStatusCode()));
                } catch (Throwable throwable) {
                    log.error("riskMinisterApprovalContract updateContractOrderStatus error", throwable);
                }
            } else {
                // 状态更新为已驳回
                contractPo.setStatus(ContractStatusEnum.REJECT.getStatus());
                ApprovalCommentDto approvalCommentDto = new ApprovalCommentDto();
                approvalCommentDto.setComment(dto.getComment());
                contractPo.setExtendedFields(JSONUtil.toJsonStr(approvalCommentDto));
            }

            contractPo.setUpdaterId(dto.getUpdaterId());
            contractPo.setUpdaterName(dto.getUpdaterName());
            LambdaQueryWrapper<ContractPo> orderPrimaryUpdateWrapper = new LambdaQueryWrapper<>();
            orderPrimaryUpdateWrapper.eq(ContractPo::getContractId, dto.getContractId());
            orderPrimaryUpdateWrapper.eq(ContractPo::getIsDeleted, 0);
            contractMapper.update(contractPo, orderPrimaryUpdateWrapper);
        }

        log.info("areaManagerApprovalContract response:{}", JSONUtil.toJsonStr(auditResult));
        RiskMinisterApprovalContractResponse riskMinisterApprovalContractResponse = new RiskMinisterApprovalContractResponse();
        riskMinisterApprovalContractResponse.setSuccess(auditResult);
        return riskMinisterApprovalContractResponse;
    }

    @Override
    public AreaManagerApprovalContractResponse areaManagerApprovalContract(AreaManagerApprovalContractRequest areaManagerApprovalContractRequest) {
        log.info("areaManagerApprovalContract request:{}", JSONUtil.toJsonStr(areaManagerApprovalContractRequest));
        AreaManagerApprovalContractDto dto = BeanUtil.copyProperties(areaManagerApprovalContractRequest, AreaManagerApprovalContractDto.class);
        setUserContextInfo(dto);
        // 1. 根据合同id查询合同信息
        ContractPo contractRo = selectContractPoByContractId(dto.getContractId());
        if (Objects.isNull(contractRo) || StrUtil.isEmpty(dto.getTaskId())) {
            throw new HMYRuntimeException(5010003);
        }
        dto.setProcessId(contractRo.getProcessId());
        // 2. 判断用户部门权限
        List<Long> deptIds = uaaFeignClientManager.getDeptIds(dto.getUpdaterId());
        if (!deptIds.contains(contractRo.getDeptId())) {
            throw new HMYRuntimeException(5010016);
        }

        // 3. 判断用户角色权限
        if (!UserContextUtil.getCurrentUser().getRoles().contains(RoleEnum.AREA_MANAGER.getRoleType())) {
            throw new HMYRuntimeException(5010016);
        }

        // 4. 判断合同是否可以审核
//        if (!ContractStatusEnum.ORDER_STATUS_CAN_AUDIT.contains(contractRo.getStatus())) {
//            throw new HMYRuntimeException(5010015);
//        }
        Boolean auditResult = Boolean.FALSE;
        ApprovalTaskRequest approvalTaskRequest = new ApprovalTaskRequest();
        Map<String, Object> variables = new HashMap<>();
        if (dto.getPass()) {
            // 通过则设置对应的流程变量
            variables.put("areaManagerApproveResult", "agree");
            variables.put("businessStatus", ContractStatusEnum.RISK_MINISTER_APPROVAL.getStatus());
            variables.put("businessStatusAlias", ContractStatusEnum.RISK_MINISTER_APPROVAL.getStatusDesc());
            approvalTaskRequest.setComment(StringUtils.isEmpty(dto.getComment()) ? "通过" : dto.getComment());
        } else {
            // 不通过则驳回到销售经理
            variables.put("areaManagerApproveResult", "reject");
            variables.put("rejectCount", 1);
            variables.put("businessStatus", ContractStatusEnum.REJECT.getStatus());
            variables.put("businessStatusAlias", ContractStatusEnum.REJECT.getStatusDesc());
            approvalTaskRequest.setComment(StringUtils.isEmpty(dto.getComment()) ? "驳回" : dto.getComment());
        }
        approvalTaskRequest.setVariables(variables);
        approvalTaskRequest.setProcessInstanceId(dto.getProcessId());
        approvalTaskRequest.setTaskId(dto.getTaskId());
        approvalTaskRequest.setApprovalStatus(dto.getPass() ? ApprovalStatusEnum.PASS.getCode() : ApprovalStatusEnum.REJECT.getCode());
        ApprovalTaskResponse approvalTaskResponse = flowTaskClientRpc.complete(approvalTaskRequest);
        if (Objects.nonNull(approvalTaskResponse) && Objects.nonNull(approvalTaskResponse.getSuccess())) {
            auditResult = approvalTaskResponse.getSuccess();
        }

        // 6. 更新合同表
        if (auditResult) {
            ContractPo contractPo = new ContractPo();
            ContractExtensionFieldDto contractExtensionFieldDto = new ContractExtensionFieldDto();
            if (Objects.nonNull(JSONUtil.toBean(contractPo.getExtendedFields(), ContractExtensionFieldDto.class))) {
                contractExtensionFieldDto = JSONUtil.toBean(contractPo.getExtendedFields(), ContractExtensionFieldDto.class);
            }
            contractExtensionFieldDto.setApprovalComments(dto.getComment());
            contractPo.setExtendedFields(JSONUtil.toJsonStr(contractExtensionFieldDto));

            // 流程审批后更新状态
            if (Objects.nonNull(dto.getPass()) && Boolean.TRUE.equals(dto.getPass())) {
                contractPo.setStatus(ContractStatusEnum.RISK_MINISTER_APPROVAL.getStatus());
            } else {
                contractPo.setStatus(ContractStatusEnum.REJECT.getStatus());
                ApprovalCommentDto approvalCommentDto = new ApprovalCommentDto();
                approvalCommentDto.setComment(dto.getComment());
                contractPo.setExtendedFields(JSONUtil.toJsonStr(approvalCommentDto));
            }

            contractPo.setUpdaterId(dto.getUpdaterId());
            contractPo.setUpdaterName(dto.getUpdaterName());
            LambdaQueryWrapper<ContractPo> orderPrimaryUpdateWrapper = new LambdaQueryWrapper<>();
            orderPrimaryUpdateWrapper.eq(ContractPo::getContractId, dto.getContractId());
            orderPrimaryUpdateWrapper.eq(ContractPo::getIsDeleted, 0);
            contractMapper.update(contractPo, orderPrimaryUpdateWrapper);
        }

        log.info("areaManagerApprovalContract response:{}", JSONUtil.toJsonStr(auditResult));
        AreaManagerApprovalContractResponse areaManagerApprovalContractResponse = new AreaManagerApprovalContractResponse();
        areaManagerApprovalContractResponse.setSuccess(auditResult);
        return areaManagerApprovalContractResponse;
    }

    private ContractPo selectContractPoByContractId(Long contractId) {
        LambdaQueryWrapper<ContractPo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ContractPo::getContractId, contractId);
        wrapper.eq(ContractPo::getIsDeleted, Boolean.FALSE);
        return contractMapper.selectOne(wrapper);
    }

    private void setUserContextInfo(BaseDto baseDto) {
        ContextUserInfo userInfo = UserContextUtil.getCurrentUser();
        if (Objects.isNull(userInfo) || Objects.isNull(userInfo.getId())) {
            throw new HMYRuntimeException(5010018);
        }
        baseDto.setDeptIds(new ArrayList<>(userInfo.getDeptIds()));
        baseDto.setRoles(userInfo.getRoles());
        baseDto.setUpdaterId(userInfo.getId());
        baseDto.setUpdaterName(userInfo.getUserName());
        baseDto.setCreatorId(userInfo.getId());
        baseDto.setCreatorName(userInfo.getUserName());
    }
}
